﻿using ET;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Core
{
    public class UnitComponent : Entity
    {
        private readonly Dictionary<long, Unit> dict = new Dictionary<long, Unit>();
        private readonly Dictionary<int, Unit> objectIdDict = new Dictionary<int, Unit>();

        public async ETTask<Unit> CreateAsync(Scene scene, int unitId)
        {
            var config = World.GetComponent<ConfigComponent>().GetConfig<UnitConfig>(unitId);

            Transform transform = default;
            if (config != null)
            {
                var prefab = await World.GetComponent<ResourceComponent>().LoadAsync<GameObject>(config.path);
                if(prefab  != null)
                {
                    transform = GameObject.Instantiate(prefab).transform;
                }
                else
                {
                    transform = new GameObject($"{unitId}").transform;
                }
            }

            var unit = scene.AddChild<Unit, int, Transform>(unitId, transform);
            unit.AddComponent<StateMachineComponent>();
#if UNITY_EDITOR
            var unitView = unit.transform.gameObject.AddComponent<UnitView>();
            unitView.target = transform;
#endif
            unit.AddComponent<NumericComponent>();
            if (config != null)
            {
                if (config.buffs != null && config.buffs.Length > 0)
                {
                    var buffComponent = unit.AddComponent<BuffComponent>();

                    foreach (var buffId in config.buffs)
                    {
                        buffComponent.AddBuff(buffId);
                    }
                }

                if (config.skills != null && config.skills.Length > 0)
                {
                    var skillComponent = unit.AddComponent<SkillComponent>();

                    foreach (var skillId in config.skills)
                    {
                        skillComponent.AddSkill(skillId);
                    }
                }
            }

            dict[unit.InstanceId] = unit;
            objectIdDict[transform.GetInstanceID()] = unit;
            return unit;
        }

        public Unit GetUnit(long instanceId)
        {
            dict.TryGetValue(instanceId, out var unit);
            return unit;
        }

        public bool HasUnit(long instanceId)
        {
            return dict.ContainsKey(instanceId);
        }

        public bool HasGameObject(GameObject gameObject)
        {
            return objectIdDict.ContainsKey(gameObject.transform.GetInstanceID());
        }

        public bool HasGameObject(Transform transform)
        {
            return objectIdDict.ContainsKey(transform.GetInstanceID());
        }

        public bool TryGetUnit(Transform transform, out Unit unit)
        {
            return objectIdDict.TryGetValue(transform.GetInstanceID(), out unit);
        }

        internal void Remove(long instanceId)
        {
            if(dict.TryGetValue(instanceId, out var unit))
            {
                dict.Remove(instanceId);
                objectIdDict.Remove(unit.transform.GetInstanceID());
                //unit?.Dispose();
            }
        }

        public override void Dispose()
        {
            base.Dispose();

            if(dict.Count > 0 )
            {
                foreach (var unit in dict.Values.ToArray())
                {
                    unit?.Dispose();
                }
                dict.Clear();
            }
            objectIdDict.Clear();
        }
    }

}